package cn.iocoder.yudao.module.xkfz.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.module.xkfz.domain.entity.basic.DepartmentScore;
import cn.iocoder.yudao.module.xkfz.domain.entity.basic.IndicatorTree;
import cn.iocoder.yudao.module.xkfz.domain.entity.operationalPerformance.MetricDirectScore;
import cn.iocoder.yudao.module.xkfz.domain.po.operationalPerformance.MetricDirectScorePo;
import cn.iocoder.yudao.module.xkfz.mapper.operationalPerformance.MetricDirectScoreMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

/**
 * 构建树
 */
@Component
public class BuildIndicatorTree {

    private final static String reportStyle = "特殊填报分数";
    @Autowired
    MetricDirectScoreMapper metricDirectScoreMapper;

    public static BuildIndicatorTree buildIndicatorTree;
    @PostConstruct
    public void init(){
        buildIndicatorTree = this;
    }
    /**
     * 构建指标树。
     *
     * @param indicatorTreeList 指标树列表，不能为 null。
     * @return 根节点列表。
     */
    public static List<IndicatorTree> buildTree(List<IndicatorTree> indicatorTreeList) {
        // 校验输入数据的完整性
        if (indicatorTreeList == null || indicatorTreeList.isEmpty()) {
            throw new IllegalArgumentException("indicatorTreeList cannot be null or empty");
        }

        List<IndicatorTree> treeList = new ArrayList<>();
        // 使用 stream 过滤出根节点，并添加到列表中
        indicatorTreeList.stream()
                .filter(person -> person.getParentId() == 0)
                .peek(treeList::add)
                .forEach(root -> addChildren(root, indicatorTreeList));
        //递归地为所有叶节点设置 `leaf` 标志为 `true` 并且赋科室分数
        markLeafNodes(treeList);
//        treeList = treeList.stream().filter(indicatorTree ->
//                indicatorTree.getIndicatorName().equals("运营绩效")).collect(Collectors.toList());
        //根据叶子节点往前赋值
        getMarkLeafNodes(null,treeList);
        return treeList;
    }

    /**
     * 为给定的父节点添加子节点。
     *
     * @param parent 父节点，不能为 null。
     * @param indicatorTreeList 指标树列表，不能为 null。
     */
    private static void addChildren(IndicatorTree parent, List<IndicatorTree> indicatorTreeList) {
        // 使用非递归方式避免栈溢出和无穷递归的风险
        ConcurrentMap<Long, IndicatorTree> treeMap = indicatorTreeList.stream()
                .collect(Collectors.toConcurrentMap(IndicatorTree::getId, t -> t));

        Deque<IndicatorTree> stack = new ArrayDeque<>();
        stack.push(parent);

        while (!stack.isEmpty()) {
            IndicatorTree current = stack.pop();
            List<IndicatorTree> childrenToAdd = new ArrayList<>();

            // 通过Map直接查找子节点，避免重复遍历
            for (IndicatorTree child : treeMap.values()) {
                if (child.getParentId().equals(current.getId())) {
                    childrenToAdd.add(child);
                    // 避免重复遍历，将子节点从map中移除
                    treeMap.remove(child.getId());
                }
            }
            if(current.getChildren()==null){
                current.setChildren(new ArrayList<>());
            }
            // 将找到的子节点一次性添加到父节点，提高效率和清晰度
            current.getChildren().addAll(childrenToAdd);

            // 将待添加的子节点入栈，以便后续处理
            childrenToAdd.forEach(stack::push);
        }
    }
    /**
     * 递归地为所有叶节点设置 `leaf` 标志为 `true`。
     *
     * @param nodes 待处理的节点列表
     */
    private static void markLeafNodes(List<IndicatorTree> nodes) {
        for (IndicatorTree node : nodes) {
            if ((node.getReportSourceStyle()!=null&&node.getReportSourceStyle().contains("特殊填报分数"))|| node.getChildren() == null || node.getChildren().isEmpty()) {
                //查询最后一个基本指标的科室得分
                List<MetricDirectScore> scorePoList = buildIndicatorTree.metricDirectScoreMapper.
                        selectList("INDICATOR_ID", node.getId());
                List<DepartmentScore> departmentScores1 = BeanUtil.copyToList(scorePoList, DepartmentScore.class);

                node.setDepartmentScores(departmentScores1);
                node.setLeaf(true);
            } else {
                markLeafNodes(node.getChildren());
            }
        }
    }
    public static double getResult(String num) {
        if(num.contains("/")){
            String [] str = num.split("/");
            return Double.parseDouble(str[0]) /Double.parseDouble(str[1]);
        }else {
            return Double.parseDouble(num);
        }

    }


    /**
     * List<IndicatorTree> previousNode
     * @param nodes
     */
    private static void getMarkLeafNodes(IndicatorTree preNode,List<IndicatorTree> nodes) {
        Map<String, Double> sumOfScoresByKsName = new HashMap<>(); // 用于累计每个部门的分数
        for (IndicatorTree node : nodes) {
            if((node.getDepartmentScores()==null||node.getDepartmentScores().size()==0)&&(
                    node.getReportSourceStyle() == null || !node.getReportSourceStyle().contains("特殊填报分数")
                    )){
                //去下一级拿到数据 来反哺这一层的数据汇总
                getMarkLeafNodes(node,node.getChildren());
            }else{
//                //特殊算法，他这个就不需要单独去计算下面子部门分数
//                if(node.getReportSourceStyle().contains("特殊填报分数")&&
//                        CollectionUtil.isNotEmpty(node.getDepartmentScores())){
//
//                }
                // 累计分数
                node.getDepartmentScores().forEach(departmentScore -> {
                    String ksName = departmentScore.getKsName();
                    String ksId = String.valueOf(departmentScore.getId());
                    double score = departmentScore.getScore()==null?0.0:getResult(departmentScore.getScore());
                    sumOfScoresByKsName.merge(ksName, score, Double::sum);
//                    sumOfScoresByKsName.put(ksName,
//                            sumOfScoresByKsName.getOrDefault(ksName, 0.0) + score);
                });
                if (preNode != null) {
                    // 更新上一层节点的分数(第一次进来是空的，所以我们下面这么写)
                    List<DepartmentScore> departmentScores = preNode.getDepartmentScores();
                    if (departmentScores != null && !departmentScores.isEmpty()) {
                        departmentScores.clear();
                    } else {
                        departmentScores = new ArrayList<>();
                    }
                    List<DepartmentScore> finalDepartmentScores = departmentScores;
                    sumOfScoresByKsName.forEach((ksName, score) ->
                            finalDepartmentScores.add(new DepartmentScore(ksName, String.valueOf(preNode.getScore()!=null&&score>=Double.valueOf(preNode.getScore())?Double.valueOf(preNode.getScore()):score))));
                    preNode.setDepartmentScores(finalDepartmentScores);
                    //getMarkLeafNodes(node,nodes);
                }
            }
            System.out.println(node);
            if(node.getDepartmentScores()==null){
                //去下一级拿到数据 来反哺这一层的数据汇总
                getMarkLeafNodes(node,node.getChildren());
            }
        }

        System.out.println(nodes);
//        getMarkLeafNodes(null,nodes);
    }

}
